#pragma once

#include <QString>
#include <QIcon>
#include <QUuid>
#include <QDateTime>
#include <QPixmap>
#include <QIcon>
#include <QFile>
#include <QDebug>
#include <QFileInfo>

// 创建命名空间
namespace model{

/*
 * ************************************************************
 *   工具函数
 * ************************************************************
*/


static inline QString getFileName(const QString& path) {
    QFileInfo fileInfo(path);
    return fileInfo.fileName();
}

// 封装一个 “宏” 作为打印日志的方式
#define TAG QString("[%1:%2]").arg(model::getFileName(__FILE__), QString::number(__LINE__))

// qDebug 打印字符串的时候，就会自动加上 " "
#define LOG() qDebug().noquote() << TAG



// 要求函数的定义如果写在 .h 中，必须加 static 或者 inline，避免链接的阶段出现“函数重定义” 问题
static inline QString formatTime(int64_t timestamp) {
    // 先把时间戳转换成 QDateTime 对象
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(timestamp);
    // 把 QDateTime 对象转成 "格式化时间"
    return dateTime.toString("MM-dd HH:mm:ss");

}

// 通过这个函数得到  秒级 的时间戳
static inline int64_t getTime() {
    return QDateTime::currentSecsSinceEpoch();
}


// 根据 QByteArray，转成 QIcon
static inline QIcon makeIcon(const QByteArray& byteArray){
    QPixmap pixmap;
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}


// 读写文件操作
// 从指定文件中，读取所有二进制内容，得到一个 QByteArray
static inline QByteArray loadFileToByteArray(const QString& path){
    QFile file(path);

    bool ok = file.open(QFile::ReadOnly);

    if (!ok) {
        LOG() << "文件打开失败"    ;
        return QByteArray();
    }

    QByteArray content = file.readAll();
    file.close();


    return content;
}

// 把 QByteArray 中的内容，写入到指定某个文件里
static inline void writeByteArrayToFile(const QString& path, const QByteArray& content) {
    QFile file(path);
    bool ok = file.open(QFile::WriteOnly);

    if (!ok) {
        LOG() << "文件打开失败";
        return ;
    }

    file.write(content);
    file.flush();   // 刷新缓冲区
    file.close();
}


/*
 * ************************************************************
 *   用户信息
 * ************************************************************
*/
class UserInfo{

public:
    QString userId = "";         //用户编号
    QString nickname = "";       //用户昵称
    QString description = "";    //用户签名
    QString phone = "";          //手机号码
    QIcon avatar;           //用户头像

};


/*
 * ************************************************************
 *   消息信息
 * ************************************************************
*/

enum MessageType{
    TEXT_TYPE,      //文本消息
    IMAGE_TYPE,     //图片消息
    FILE_TYPE,      //文件消息
    SPEECH_TYPE     //语音消息
};


class Message{
public:
    QString messageId = "";          //消息编号
    QString chatSessionId = "";      //消息所属会话的编号， 一个会话对应多个消息
    QString time = "";               //消息时间，通过格式化时间的方式，形如：08-23-08:00:00
    MessageType messageType;         //消息类型
    UserInfo sender;                 //发送者消息
    QByteArray content;              //消息正文内容 (可能为文本、图片、语音)
    QString fileId = "";             //文件的身份标识，当消息类型为 文件，图片，语音时，fileId才有效，当消息类型为 文本时，fileId = ""
    QString fileName = "";           //文件名称，当消息类型为 文件消息时，才有效，其他消息均为 ""


    // 此处的 extraInfo 目前只是在消息类型为文件消息时，作为 "文件名" 补充--- 因为文件信息打开时是需要显示文件名字的，图片、语音虽然也是”文件“，但是打开的时候我们只需要拿到文件数据而不需要显示文件名
    // 这个 extraInfo 其实就可以理解为 fileName，之后也可扩展为其他信息
    static Message makeMessage(MessageType messageType, const QString& chatSessionId, const UserInfo& sender,
                               const QByteArray& content, const QString& extraInfo) {
        if (messageType == TEXT_TYPE) {
            return makeTextMessage(chatSessionId, sender, content);
        } else if (messageType == SPEECH_TYPE) {
            return makeSpeechMessage(chatSessionId, sender, content);
        } else if (messageType == IMAGE_TYPE) {
            return makeImageMessage(chatSessionId, sender, content);
        } else if (messageType == FILE_TYPE) {
            return makeFileMessage(chatSessionId, sender, content, extraInfo);
        } else {
            // 未知的消息类型
            return Message();
        }
    }

private:
    // 通过这个方法生成唯一的 messageId
    static QString makeId() {
        return "M" + QUuid::createUuid().toString().sliced(25, 12);   // sliced表示截取 16 进制字符串的部分字符
    }

    static Message makeTextMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content) {
        Message message;
        // 此处需要确保，设置的 messageId 是唯一的
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());    //生成一个格式化时间
        message.content = content;
        message.messageType = TEXT_TYPE;
        // 对于文本消息来说，这俩属性不使用，设为 ""
        message.fileId = "";
        message.fileName = "";
        return message;
    }


    static Message makeSpeechMessage(const QString& chatSessionId, const
                                         UserInfo& sender, const QByteArray& content)   {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.content = content;
        message.messageType = SPEECH_TYPE;
        // fileId 后续使用的时候再进一步设置
        message.fileId = "";
        // fileName 不适用，直接设置为 ""
        message.fileName = "";
        return message;
    }

    static Message makeImageMessage(const QString& chatSessionId, const
                                    UserInfo& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.content = content;
        message.messageType = IMAGE_TYPE;
        // fileId 后续使用的时候再进一步设置
        message.fileId = "";
        // fileName 不使用，直接设置为 ""
        message.fileName = "";
        return message;
    }

    static Message makeFileMessage(const QString& chatSessionId, const
                                   UserInfo& sender, const QByteArray& content, const QString& fileName) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.content = content;
        message.messageType = FILE_TYPE;
        // fileId 后续使用的时候再进一步设置
        message.fileId = "";
        message.fileName = fileName;
        return message;

    }
};





/*
 * ************************************************************
 *   会话信息
 * ************************************************************
*/

class ChatSessionInfo{
public:
    QString chatSessionId = "";       //会话编号
    QString chatSessionName = "";     //会话名字，如果是单聊，会话名字就是对方的昵称，如果是群聊，名字则为群聊的名称
    Message lastMessage;              //表示最新消息
    QIcon avatar;                     //会话头像，如果是单聊，头像是对方的头像，如果是群聊，头像则为群头像
    QString userId = "";              // 单聊为dui

};


}   // end model
